package com.hb.trade.server.project.section.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hb.core.pojo.Attachment;
import com.hb.core.pojo.Attachments;
import com.hb.core.pojo.enums.SectionStatusEnum;
import com.hb.core.pojo.parent.PageResult;
import com.hb.core.pojo.project.file.entity.BidFileInfo;
import com.hb.core.pojo.project.opening.dto.BidOpeningScheduleDTO;
import com.hb.core.pojo.project.opening.entity.BidOpeningSchedule;
import com.hb.core.pojo.project.section.dto.BidSectionDTO;
import com.hb.core.pojo.project.section.dto.BidSectionTenderDTO;
import com.hb.core.pojo.project.section.entity.BidSection;
import com.hb.core.pojo.project.section.entity.BidSectionTender;
import com.hb.trade.server.project.file.service.BidFileInfoService;
import com.hb.trade.server.project.opening.service.BidOpeningScheduleService;
import com.hb.trade.server.project.section.manager.BidSectionTenderManager;
import com.hb.trade.server.project.section.service.raw.BidSectionService;
import com.hb.trade.server.project.section.service.raw.BidSectionTenderService;
import com.hb.trade.server.project.section.service.raw.SupplyBidSignupService;
import org.fzzn.core.model.enums.MsgEnum;
import org.fzzn.core.model.msg.Message;
import org.fzzn.core.util.MsgUtil;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 投标人投标信息 前端控制器
 * </p>
 *
 * @author admin
 * @since 2021-11-09
 */
@RestController
public class BidSectionTenderController {

    protected final BidSectionTenderService bidSectionTenderService;
    protected final BidSectionService bidSectionService;
    protected final SupplyBidSignupService supplyBidSignupService;
    protected final BidOpeningScheduleService bidOpeningScheduleService;

    public BidSectionTenderController(BidSectionTenderService bidSectionTenderService,
                                      BidSectionService bidSectionService,
                                      SupplyBidSignupService supplyBidSignupService,
                                      BidOpeningScheduleService bidOpeningScheduleService) {
        this.bidSectionTenderService = bidSectionTenderService;
        this.bidSectionService = bidSectionService;
        this.supplyBidSignupService = supplyBidSignupService;
        this.bidOpeningScheduleService = bidOpeningScheduleService;
    }

    /**
     * 保存投标信息
     *
     * @param bidSectionTenderDto 投标信息
     * @author gaoyf
     * @date 2021-11-9
     */
    @PostMapping("/bidSectionTender/save")
    public Message<Boolean> save(@RequestBody BidSectionTenderDTO bidSectionTenderDto) {
        if (null == bidSectionTenderDto.getSectionId()) {
            return MsgUtil.fail(MsgEnum.INCORRECT_PARAM.msg());
        }
        if (null == bidSectionTenderDto.getTenderDocument()) {
            return MsgUtil.fail("请先上传投标文件");
        }
        bidSectionTenderDto.setStatus(0);
        Boolean flag = bidSectionTenderService.saveOrUpdate(bidSectionTenderDto);
        return MsgUtil.msg(flag);
    }

    /**
     * 递交投标信息
     *
     * @param bidSectionTenderDto 投标信息
     * @author gaoyf
     * @date 2021-11-9
     */
    @PostMapping("/bidSectionTender/submit")
    public Message<Boolean> submit(@RequestBody BidSectionTenderDTO bidSectionTenderDto) {
        BidSectionTenderManager sectionTenderManager = bidSectionTenderDto.to(BidSectionTenderManager.class);
        Message<Boolean> validMsg = sectionTenderManager.submitValid();
        if (validMsg != null) {
            return validMsg;
        }

        bidSectionTenderDto.setStatus(1);
        bidSectionTenderDto.setSuccessTime(LocalDateTime.now());
        boolean flag = bidSectionTenderService.saveOrUpdate(bidSectionTenderDto);
        // 递交投标文件成功之后, 修改报名表中的投标文件递交状态
        if (flag) {
            supplyBidSignupService.updateTenderFileStatus(
                    bidSectionTenderDto.getSectionId(),
                    bidSectionTenderDto.getOrgId(),
                    bidSectionTenderDto.getBidderId(), 1);
        }
        return MsgUtil.msg(flag);
    }

    /**
     * 在线制作投标文件 的递交操作
     * @param bidSectionTenderDTO
     * @return
     */
    @PostMapping("/bidSectionTender/submitOnline")
    public Message<Boolean> submitOnline(@RequestBody BidSectionTenderDTO bidSectionTenderDTO) {
        if (bidSectionTenderDTO.getId() == null) {
            return MsgUtil.fail(MsgEnum.INCORRECT_PARAM.msg());
        }

        BidSectionTender sectionTender = bidSectionTenderService.getById(bidSectionTenderDTO.getId());
        if (bidSectionTenderDTO.getReceiptFile() != null) {
            sectionTender.setReceiptFile(bidSectionTenderDTO.getReceiptFile());
        }

        if (CollUtil.isEmpty(sectionTender.getTenderDocument())) {
            return MsgUtil.fail("请先上传并机密投标文件");
        }

        //判断标段状态，只有标段状态为 NOTICE_ISSUED(1465922770142670849L, 146, "项目公告已发布") 时才允许继续投标
        BidSectionService bidSectionService = SpringUtil.getBean(BidSectionService.class);
        BidSection bidSection = bidSectionService.getById(sectionTender.getSectionId());
        if (null == bidSection) {
            return MsgUtil.fail("未获取到标段信息");
        }

        SectionStatusEnum ins = SectionStatusEnum.getIns(bidSection.getSectionStatus());
        if (SectionStatusEnum.BID_FILE_SOLD != ins) {
            return MsgUtil.fail("当前标段状态不允许继续投标");
        }

        sectionTender.setStatus(1);
        sectionTender.setSuccessTime(LocalDateTime.now());
        boolean update = bidSectionTenderService.updateById(sectionTender);

        return MsgUtil.msg(update);
    }

    /**
     * 撤回投标信息
     *
     * @param bidSectionTenderDto 投标信息
     * @author gaoyf
     * @date 2021-11-9
     */
    @PostMapping("/bidSectionTender/withdraw")
    public Message<Boolean> withdraw(@RequestBody BidSectionTenderDTO bidSectionTenderDto) {
        if (bidSectionTenderDto.getId() == null) {
            return MsgUtil.fail("投标信息不存在");
        }
        // 判断是否开标结束
        BidSectionTender byId = bidSectionTenderService.getById(bidSectionTenderDto.getId());
        BidSection bidSection = bidSectionService.getById(byId.getSectionId());

        SectionStatusEnum sectionStatus = SectionStatusEnum.getIns(bidSection.getSectionStatus());
        // 如果当前标段状态大于项目公告已发布 说明已经开标了 不允许撤回文件
        if (sectionStatus.getCode() >= SectionStatusEnum.BID_OPENING.getCode()) {
            return MsgUtil.fail("当前标段已开标，不允许撤回投标文件");
        }

        bidSectionTenderDto.setStatus(2);
        //TODO set null不起作用, mybaits 属性为null时默认不做处理
        bidSectionTenderDto.setSuccessTime(null);
        bidSectionTenderDto.setWithdrawTime(LocalDateTime.now());
        boolean flag = bidSectionTenderService.updateById(bidSectionTenderDto);
        return MsgUtil.msg(flag);
    }

    /**
     * 投标信息详情
     *
     * @param sectionId 标段ID
     * @author gaoyf
     * @date 2021-11-9
     */
    @GetMapping("/bidSectionTender/detail")
    public Message<BidSectionTenderDTO> detail(Long sectionId, Long tenderId) {
        if (sectionId == null || tenderId == null) {
            return MsgUtil.msg(MsgEnum.LOGIN_ERROR);
        }
        BidSectionTenderDTO bidSectionTender = bidSectionTenderService.getBySectionIdAndTenderId(sectionId, tenderId);
        return MsgUtil.success(Objects.requireNonNullElseGet(bidSectionTender, BidSectionTenderDTO::new));
    }

    @PostMapping("/bidSectionTender/sectionTenderDetail")
    public Message<BidSectionTenderDTO> sectionTenderDetail(@RequestBody BidSectionTenderDTO bidSectionTenderDTO) {
        Long sectionId = bidSectionTenderDTO.getSectionId();
        if (sectionId == null) {
            return MsgUtil.fail("标段ID不能为空");
        }
        Long orgId = bidSectionTenderDTO.getOrgId();
        if (orgId == null) {
            return MsgUtil.fail("企业ID不能为空");
        }

        BidSectionTenderDTO bidSectionTender = bidSectionTenderService.getBySectionIdAndOrgId(sectionId, orgId);

        if (bidSectionTender == null) {
            bidSectionTender = new BidSectionTenderDTO();
        }

        // 判断开标一览表是否有内容
        if (StrUtil.isEmpty(bidSectionTender.getOpeningScheduleContent())) {
            bidSectionTender.setOpeningScheduleHaveContent(0);
        } else {
            try {
                JSONArray jsonArray = JSONUtil.parseArray(bidSectionTender.getOpeningScheduleContent());
                if (jsonArray.size() == 0) {
                    bidSectionTender.setOpeningScheduleHaveContent(0);
                } else {
                    bidSectionTender.setOpeningScheduleHaveContent(1);
                }
            } catch (Exception e) {
                bidSectionTender.setOpeningScheduleHaveContent(0);
            }
        }

        // 填充开标一览表信息
        List<BidOpeningSchedule> bidOpeningScheduleList = bidOpeningScheduleService.listBySectionId(sectionId);
        BidOpeningScheduleDTO bidOpeningScheduleDTO = new BidOpeningScheduleDTO();
        bidOpeningScheduleDTO.setBidOpeningSchedules(bidOpeningScheduleList);
        bidSectionTender.setOpeningSchedule(bidOpeningScheduleDTO);

        // 设置提交按钮的值，当有投标文件并且不是撤回状态时，才
        if (CollectionUtil.isNotEmpty(bidSectionTender.getTenderPdfSignature())
                && CollectionUtil.isNotEmpty(bidSectionTender.getUnencryptedDocument())
                && !bidSectionTender.getStatus().equals(1)) {
            bidSectionTender.setEnableSubmitFlag(1);
        } else {
            bidSectionTender.setEnableSubmitFlag(0);
        }

        return MsgUtil.success(bidSectionTender);
    }

    /**
     * 根据标段Id统计投标总数、已递交、未递交数量
     *
     * @param sectionId
     * @return
     */
    @GetMapping("/bidSectionTender/countTender")
    public Message<JSONObject> countTender(Long sectionId) {
        if (null == sectionId) {
            return MsgUtil.fail(MsgEnum.INCORRECT_PARAM.msg());
        }
        JSONObject jsonObject = new JSONObject();
        //TODO 投标总数不好统计，经与产品沟通，先不处理总数与未递交数量
        //查询递交标书数量
        Long count = bidSectionTenderService.count(new LambdaQueryWrapper<BidSectionTender>()
                .eq(BidSectionTender::getSectionId, sectionId)
                .eq(BidSectionTender::getStatus, 1));
        jsonObject.putOpt("submitCount", count.intValue());
        return MsgUtil.success(jsonObject);
    }

    /**
     * 投标信息列表
     *
     * @param bidSectionTender 查询条件
     * @author gaoyf lixiang
     * @date 2021-11-9
     */
    @PostMapping("/bidSectionTender/list")
    @SuppressWarnings("rawtypes")
    public Message<PageResult> list(@RequestBody BidSectionTenderDTO bidSectionTender) {
        if (bidSectionTender.getSectionId() == null) {
            return MsgUtil.fail("标段ID不能为空");
        }
        PageResult<BidSectionTenderDTO> bidSectionTenderPageResult = bidSectionTenderService.listBidSectionTender(bidSectionTender);
        return MsgUtil.success(bidSectionTenderPageResult);
    }

    /**
     * 根据主键Id查询投标详情
     *
     * @param bidSectionTenderDTO
     * @return
     */
    @PostMapping("/bidSectionTender/getDetailById")
    public Message<BidSectionTender> getDetailById(@RequestBody BidSectionTenderDTO bidSectionTenderDTO) {
        if (null == bidSectionTenderDTO.getId()) {
            return MsgUtil.fail(MsgEnum.INCORRECT_PARAM.msg());
        }
        BidSectionTender bidSectionTender = bidSectionTenderService.getById(bidSectionTenderDTO.getId());
        return MsgUtil.success(bidSectionTender);
    }

    /**
     * 根据标段Id查询投标人的登录用户名username
     * (目前用于开标大厅消息构造消费者)
     *
     * @param sectionId
     * @return
     */
    @GetMapping("/bidSectionTender/getBidderUserNameBySectionId/{sectionId}")
    public Message<List<String>> getBidderUserNameBySectionId(@PathVariable("sectionId") Long sectionId) {
        List<String> usernameList = bidSectionTenderService.getBidderUserNameBySectionId(sectionId);
        return MsgUtil.success(usernameList);
    }

    /**
     * 获取指定标段和投标人ID的投标文件
     *
     * @param sectionId
     * @return
     */
    @PostMapping("/bidSectionTender/tenderDocument")
    public Message<Attachment> tenderDocument(Long sectionId, Long tenderId) {
        Message<BidSectionTenderDTO> detail = detail(sectionId, tenderId);
        if (detail.isFail()) {
            return MsgUtil.msg(detail.getCode(), detail.getMessage(), null);
        }
        BidSectionTender data = detail.getData();
        // 判断投标文件递交状态
        if (!Integer.valueOf(1).equals(data.getStatus())) {
            return MsgUtil.fail("投标文件未递交");
        }
        Attachments documents = data.getTenderDocument();
        if (CollUtil.isEmpty(documents)) {
            return MsgUtil.fail("未能获取投标文件信息");
        }
        return MsgUtil.success(documents.get(0));
    }

    /**
     * 保存解密后的投标文件
     *
     * @param sectionTender#decTenderDocument 后端保存逻辑会将这个对象转换为JSON字符串直接保存, 无其他逻辑
     * @return
     */
    @PostMapping("/bidSectionTender/saveDecryptFile")
    public Message<Boolean> saveDecryptFile(@RequestBody BidSectionTenderDTO sectionTender) throws Exception {
        // 必要参数判断
        Long sectionId = sectionTender.getSectionId();
        if (sectionId == null) {
            return MsgUtil.msg(MsgEnum.INCORRECT_PARAM);
        }
        Long bidderId = sectionTender.getBidderId();
        if (bidderId == null) {
            return MsgUtil.msg(MsgEnum.INCORRECT_PARAM);
        }
        Attachments decTenderDocument = sectionTender.getDecTenderDocument();

        // 解密后的文件不为空
        if (CollUtil.isNotEmpty(decTenderDocument)) {
            // 获取解密后的PDF文件
            Attachments tenderPDF = sectionTender.getTenderPdf();
            QueryWrapper<BidSectionTender> wrapper = BidSectionTender.wrapper();
            wrapper.eq("bidder_id", bidderId)
                    .eq("section_id", sectionId)
                    .last("limit 1");
            // 查询元数据
            BidSectionTender one = bidSectionTenderService.getOne(wrapper);
            one.setDecTenderDocument(decTenderDocument);
            one.setTenderPdf(tenderPDF);
            // 更新
            bidSectionTenderService.updateById(one);
        }
        return MsgUtil.success();
    }

    /**
     * 保存投标文件信息
     * @param sectionTenderDTO
     * @return
     */
    @PostMapping("/bidSectionTender/saveTenderFileInfo")
    public Message<BidSectionTender> saveTenderFileInfo(@RequestBody BidSectionTenderDTO sectionTenderDTO) {
        Long id = bidSectionTenderService.saveTenderFileInfo(sectionTenderDTO);
        if (id != null) {
            BidSectionTender bidSectionTender = new BidSectionTender();
            bidSectionTender.setId(id);
            return MsgUtil.success(bidSectionTender);
        }
        return MsgUtil.msg(MsgEnum.FAILURE);
    }

    /**
     * @param bidSectionTenderDTO:
     * @Description: 获得投标成功的列表接口
     * @Author: zhongdl
     * @Date:2022/2/15 15:46
     * @return: {@link Message< List< BidSectionTenderDTO>> }
     **/
    @PostMapping("/bidSectionTender/listBidSectionTender")
    public Message<List<BidSectionTenderDTO>> listBidSectionTender(@RequestBody BidSectionTenderDTO bidSectionTenderDTO) {
        List<BidSectionTenderDTO> bidSectionTender = bidSectionTenderService.listDecryptionBidSectionTender(bidSectionTenderDTO.getSectionId(), bidSectionTenderDTO.getStatus(),bidSectionTenderDTO.getDecryptFlag());
        return MsgUtil.success(bidSectionTender);
    }


    /**
     * 根据标段查询投标人
     *
     * @author yuezheng
     * @param bidSectionTenderDTO
     * @return List<BidSectionTender>
     * @date 2022/4/19 11:43 AM
     */
    @PostMapping("/bidSectionTender/listBidSectionTenderBySectionId")
    Message<List<BidSectionTender>> listBidSectionTenderBySectionId(@RequestBody BidSectionTenderDTO bidSectionTenderDTO){
        QueryWrapper<BidSectionTender> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BidSectionTender::getSectionId, bidSectionTenderDTO.getSectionId());
        List<BidSectionTender> list = bidSectionTenderService.list(queryWrapper);
        return MsgUtil.success(list);
    }
}
